package com.erdos.message.entity;

import javax.jms.Destination;
import javax.jms.Queue;
import javax.jms.Topic;

import org.apache.commons.lang.builder.ToStringBuilder;

import com.erdos.common.entity.AbstractEntity;
import com.erdos.message.JmsSessionLocator;
import com.erdos.message.channel.NullMessageChannel;

public class MessageChannel extends AbstractEntity {
	public static enum DestinationType {queue, topic};
	
	/**
	 * the message type id
	 */
	private String messageTypeId;
	/**
	 * message type name
	 */
	private String messageTypeName;
	
	/**
	 * Topic or Queue, default is Queue, determined by the Destination when setting the JNDI.
	 * {@link #setDestination(String) setDestination}
	 */
	private DestinationType type=DestinationType.queue;
	
	/**
	 * jndi name of the Jms Destination, queue or topic
	 */
	private String destination;
	/**
	 * by default, this will be set when setting the jndiName
	 */
	private Destination channel;
	/**
	 * to group the <code>destination</code>.
	 * the same destination must refer to the same one clientId,
	 * and different destination can group into one clientId,
	 * also used to manage the Jms Connection.
	 */
	private String clientId;
	
	private boolean waived;
	
	private MessageHandlerMapping msgHandlerMapping;
	
	
	public MessageChannel() { }
	
	public MessageChannel(String msgTypeId, String destination) {
		this.messageTypeId=msgTypeId;
	}	
	
	public String getMessageTypeId() {
		return messageTypeId;
	}

	/**
	 * @return the messageTypeName
	 */
	public String getMessageTypeName() {
		return messageTypeName;
	}

	/**
	 * @param messageTypeName the messageTypeName to set
	 */
	public void setMessageTypeName(String messageTypeName) {
		this.messageTypeName = messageTypeName;
	}

	public void setMessageTypeId(String msgTyped) {
		this.messageTypeId = msgTyped;
	}

	public DestinationType getType() {
		return type;
	}

	private void setType(Destination channel) {
		if(this.channel instanceof Topic) {
			this.type =DestinationType.topic;
		} else if (this.channel instanceof Queue) {
			this.type =DestinationType.queue;
		}		
	}

	public String getDestination() {
		return destination;
	}
	public void setDestination(String jndiName) {
		this.destination = jndiName;
		this.setChannel(null); //reset Channel to null once destination changed
	}
	
	/**
	 * @return the clientId
	 */
	public String getClientId() {
		return clientId;
	}

	/**
	 * @param clientId the clientId to set
	 */
	public void setClientId(String clientId) {
		this.clientId = clientId;
	}
	
	public Destination getChannel() {
		if(this.channel==null) {
			this.setChannel(this.destination);
		}
		return channel;
	}	
	
	private void setChannel(String jndiName) {
		if(jndiName==null || jndiName.trim().length()==0) {
			this.channel=null;
		} else {
			try {
				this.channel = JmsSessionLocator.locateDestination(jndiName);
				this.setType(channel);
			} catch (RuntimeException ex) {
				System.err.println("failed to locate the channel: " + jndiName);
			}
		}		
	}
	
	/**
	 * @return the waived
	 */
	public boolean isWaived() {
		return waived;
	}

	/**
	 * @param waived the waived to set
	 */
	public void setWaived(boolean waived) {
		this.waived = waived;
	}

	/**
	 * @return the msgHandlerMapping
	 */
	public MessageHandlerMapping getMsgHandlerMapping() {
		return msgHandlerMapping;
	}

	/**
	 * @param msgHandlerMapping the msgHandlerMapping to set
	 */
	public void setMsgHandlerMapping(MessageHandlerMapping msgHandlerMapping) {
		this.msgHandlerMapping = msgHandlerMapping;
	}

	public boolean isNullMessageChannel() {
		return this.getChannel().equals(NullMessageChannel.getInstance());
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((messageTypeId == null) ? 0 : messageTypeId.hashCode());
		return result;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (!(obj instanceof MessageChannel))
			return false;
		final MessageChannel other = (MessageChannel) obj;
		if (messageTypeId == null) {
			if (other.messageTypeId != null)
				return false;
		} else if (!messageTypeId.equals(other.messageTypeId))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return new ToStringBuilder(this).append(this.messageTypeId)
			.append(this.messageTypeName).append(this.type)
			.append(this.destination).append(this.channel).append(this.clientId)
			.toString();
	}
	
}
